package com.parkingwang.learning.rx2;

import io.reactivex.*;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;

public class Demo2 {

    static int gobelToken = -1;


    public static void main(String[] args) {


        Observable.create(new ObservableOnSubscribe<NetworkData>() {
            @Override
            public void subscribe(ObservableEmitter<NetworkData> emitter) throws Exception {
                NetworkData networkData = new NetworkData(gobelToken, "得到的网络数据");
                System.out.println("发射：" + networkData);
                emitter.onNext(networkData);
                emitter.onComplete();
            }
        })
                .flatMap(new Function<NetworkData, ObservableSource<NetworkData>>() {
                    @Override
                    public ObservableSource<NetworkData> apply(NetworkData networkData) throws Exception {
                        System.out.println("转换：" + networkData);
                        if (networkData.code == -1) {
                            return Observable.error(new TokenExpireException());
                        } else if (networkData.code == 200) {
                            return Observable.just(networkData);
                        }
                        return Observable.error(new OtherApiException());
                    }
                })

                .retryWhen(new Function<Observable<Throwable>, ObservableSource<?>>() {
                    @Override
                    public ObservableSource<?> apply(Observable<Throwable> throwableObservable) throws Exception {
                        return throwableObservable.flatMap(new Function<Throwable, ObservableSource<?>>() {
                            @Override
                            public ObservableSource<?> apply(Throwable throwable) throws Exception {
                                if (throwable instanceof TokenExpireException) {
                                    //模拟更新token
                                    return Observable.just(200)
                                            .doOnNext(new Consumer<Integer>() {
                                                @Override
                                                public void accept(Integer code) throws Exception {
                                                    System.out.println("保存token到本地,retryWhen()会重新发射一遍数据");
                                                    gobelToken = code;
                                                }
                                            });
                                }
                                return Observable.error(throwable);
                            }
                        });
                    }
                })
                .subscribe(new Observer<NetworkData>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        System.out.println("加载中....");
                    }

                    @Override
                    public void onNext(NetworkData networkData) {
                        System.out.println(networkData.data);
                    }

                    @Override
                    public void onError(Throwable e) {
                        System.out.println("onError...." + e.toString());
                    }

                    @Override
                    public void onComplete() {
                        System.out.println("onComplete....");
                    }
                });
    }

    static class NetworkData {
        int code;//200成功，-1token过期
        String data;

        public NetworkData(int code, String data) {
            this.code = code;
            this.data = data;
        }

        @Override
        public String toString() {
            return "NetworkData{" +
                    "code=" + code +
                    ", data='" + data + '\'' +
                    '}';
        }
    }

    static class TokenExpireException extends Exception {

    }

    static class OtherApiException extends Exception {
    }


}
